﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Inventory;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System.Windows.Media;
using Action = Styx.TreeSharp.Action;

namespace TuanHA_Monk
{
    public partial class Classname
    {
        #region Attackable

        public bool Attackable(WoWUnit target)
        {
            if (ValidUnit(target) && target.Distance < 40 && !Invulnerable(target) && !InvulnerableMagic(target) &&
                (DebuffCCBreakonDamage(target) <= 0) && IsEnemy(target) &&
                target.InLineOfSpellSight)
            {
                return true;
            }
            return false;
        }

        //prevent double ValidUnit Check
        public bool AttackableValid(WoWUnit target)
        {
            if (target.Distance < 40 && !Invulnerable(target) && !InvulnerableMagic(target) &&
                (DebuffCCBreakonDamage(target) <= 0) && IsEnemy(target) &&
                target.InLineOfSpellSight)
            {
                return true;
            }
            return false;
        }

        #endregion

        #region  BattleStandard

        public Composite UseBattleStandard()
        {
            return
                new Decorator(
                    ret =>
                    Me.Combat && Me.HealthPercent < THSettings.Instance.SHealthStone && Me.CurrentTarget != null &&
                    Me.CurrentTarget.CurrentHealth > Me.HealthPercent && Me.CurrentMap.IsBattleground,
                    new Action(delegate
                                   {
                                       if (Me.IsAlliance)
                                       {
                                           WoWItem bs = Me.BagItems.FirstOrDefault(o => o.Entry == 18606);
                                           //18606 Alliance Battle Standard

                                           if (!Me.HasAura("Alliance Battle Standard") && bs != null &&
                                               bs.CooldownTimeLeft.TotalMilliseconds <= MyLatency)
                                           {
                                               bs.Use();
                                               //Lua.DoString("RunMacroText(\"/5 Used Healthstone\")");
                                               //Lua.DoString("RunMacroText(\"/s Used Battle Standard\")");
                                               Logging.Write("Use Battle Standard at " + Me.HealthPercent + "%");
                                           }
                                       }

                                       if (Me.IsHorde)
                                       {
                                           WoWItem bs = Me.BagItems.FirstOrDefault(o => o.Entry == 18607);
                                           //18606 Horde Battle Standard

                                           if (!Me.HasAura("Horde Battle Standard") && bs != null &&
                                               bs.CooldownTimeLeft.TotalMilliseconds <= MyLatency)
                                           {
                                               bs.Use();
                                               //Lua.DoString("RunMacroText(\"/5 Used Healthstone\")");
                                               //Lua.DoString("RunMacroText(\"/s Used Battle Standard\")");
                                               Logging.Write("Use Battle Standard at " + Me.HealthPercent + "%");
                                           }
                                       }

                                       return RunStatus.Failure;
                                   })
                    );
        }

        #endregion

        #region CastSpell

        public DateTime HoldRotationWhileFlying = DateTime.Now;
        public string LastCastSpell = "";
        public WoWUnit LastCastUnit;
        public WoWUnit LastCastUnitSoothingMist = Me;
        public DateTime LastCastTime = DateTime.Now;

        public void CastSpell(string spellName, WoWUnit u)
        {
            if (u == null || !u.IsValid)
            {
                return;
            }

            // [Soothing Mist] [Surging Mist] [Enveloping Mist]
            if (Me.IsCasting && Me.ChanneledCastingSpellId == 115175 &&
                spellName != "Soothing Mist" &&
                spellName != "Surging Mist" &&
                spellName != "Enveloping Mist")
            {
                SpellManager.StopCasting();
            }


            SpellManager.Cast(spellName, u);

            //Prevent spamming
            if (LastCastUnit != u || spellName != LastCastSpell || LastCastTime + TimeSpan.FromMilliseconds(500) < Now)
            {
                string barTwo;
                if (Me.HasAura("Stance of the Wise Serpent"))
                {
                    barTwo = "Mana: " + Math.Round(Me.ManaPercent);
                }
                else
                {
                    barTwo = " Energy: " + Me.EnergyPercent;
                }
                if (AttackSpells.Contains(spellName))
                {
                    Logging.Write(Colors.Orange, DateTime.Now.ToString("ss:fff") + " - HP: " +
                                                 Math.Round(Me.HealthPercent) + "% - " + barTwo +
                                                 " - Chi: " + Me.CurrentChi + " - " +
                                                 u.Class + " - " + Math.Round(u.Distance) + "y - " +
                                                 Math.Round(u.HealthPercent) + "% hp - " + spellName);
                }
                else if (DefendSpells.Contains(spellName))
                {
                    Logging.Write(Colors.GreenYellow, DateTime.Now.ToString("ss:fff") + " - HP: " +
                                                      Math.Round(Me.HealthPercent) + "% - Energy: " +
                                                      barTwo + " - Chi: " + Me.CurrentChi + " - " +
                                                      u.Class + " - " + Math.Round(u.Distance) + "y - " +
                                                      Math.Round(u.HealthPercent) + "% hp - " + spellName);
                }
                else if (SpecialSpells.Contains(spellName))
                {
                    Logging.Write(Colors.OrangeRed, DateTime.Now.ToString("ss:fff") + " - HP: " +
                                                    Math.Round(Me.HealthPercent) + "% - " + barTwo +
                                                    " - Chi: " + Me.CurrentChi + " - " +
                                                    u.Class + " - " + Math.Round(u.Distance) + "y - " +
                                                    Math.Round(u.HealthPercent) + "% hp - " + spellName);
                }
                else
                {
                    Logging.Write(Colors.Yellow, DateTime.Now.ToString("ss:fff") + " - HP: " +
                                                 Math.Round(Me.HealthPercent) + "% - " + barTwo +
                                                 " - Chi: " + Me.CurrentChi + " - " +
                                                 u.Class + " - " + Math.Round(u.Distance) + "y - " +
                                                 Math.Round(u.HealthPercent) + "% hp - " + spellName);
                }
            }

            LastCastTime = DateTime.Now;
            LastCastSpell = spellName;
            LastCastUnit = u;

            //Store LastCastUnitSoothingMist
            if (spellName == "Soothing Mist")
            {
                LastCastUnitSoothingMist = LastCastUnit;
            }

            //Store time start Roll/Fly
            if (spellName == "Flying Serpent Kick" || spellName == "Roll")
            {
                HoldRotationWhileFlying = DateTime.Now;
            }

            TickMilisecond = DateTime.Now;

            if (!NoGCDSpells.Contains(spellName))
            {
                UpdateGCD();
            }
        }

        #endregion

        #region CanCleanse

        public bool CanCleanse(WoWAura aura)
        {
            //if (aura == null)
            //    return false;

            //if (aura.Spell.DispelType == WoWDispelType.Disease || aura.Spell.DispelType == WoWDispelType.Magic ||
            //    aura.Spell.DispelType == WoWDispelType.Poison)
            if (aura.Spell.DispelType != WoWDispelType.None)
            {
                //Logging.Write("CanCleanse: " + aura.Name + " - " + aura.SpellId);
                return true;
            }
            return false;
        }

        #endregion

        #region ConstantFace

        public void ConstantFace(WoWUnit unit)
        {
            if (!IsOverrideModeOn && !Me.IsSafelyFacing(unit))
            {
                WoWMovement.ConstantFace(unit.Guid);
            }
        }

        #endregion

        #region CountDebuff

        public static double CountDebuff(WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                int numberofDebuff =
                    u.Debuffs.Values.Count(
                        debuff =>
                        (debuff.Spell.DispelType == WoWDispelType.Magic ||
                         debuff.Spell.DispelType == WoWDispelType.Poison ||
                         debuff.Spell.DispelType == WoWDispelType.Disease));

                //foreach (var debuff in u.Debuffs.Values)
                //{
                //    if (debuff.Spell.DispelType != WoWDispelType.None)
                //    {
                //        numberofDebuff = numberofDebuff + 1;
                //    }
                //}
                return numberofDebuff;
            }
        }


        public static double CountDebuffCanCleanse(WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                int numberofDebuff =
                    u.Debuffs.Values.Count(debuff => ListAllCanCleanseDebuff.Contains("[" + debuff.SpellId + "]"));
                return numberofDebuff;
            }
        }

        #endregion

        #region Debuff

        public WoWAura CurrentDebuff;

        #region DebuffCC

        public double DebuffCC(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.Debuffs.Values.Where(a => ListCC.Contains("[" + a.SpellId + "]")).OrderBy(
                        a => a.TimeLeft).FirstOrDefault();

                if (longestDebuff == null)
                {
                    return 0;
                }

                //if (target == Me)
                //{
                //    Logging.Write("Crowd Control: " + longestDebuff.Name + " - " +
                //                  longestDebuff.TimeLeft.TotalMilliseconds);
                //}
                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        public double DebuffCCCleanseASAP(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.Debuffs.Values.Where(a => ListCleanseASAP.Contains("[" + a.SpellId + "]")).OrderBy(
                        a => a.TimeLeft).
                        FirstOrDefault();

                if (longestDebuff == null || !ListCCCanCleanse.Contains("[" + longestDebuff.SpellId + "]"))
                {
                    return 0;
                }

                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        public double DebuffCCBreakonDamage(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.Debuffs.Values.Where(a => ListCC.Contains("[" + a.SpellId + "]")).OrderBy(
                        a => a.TimeLeft).FirstOrDefault();

                if (longestDebuff == null || !ListCCBreakonDamage.Contains("[" + longestDebuff.SpellId + "]"))
                {
                    return 0;
                }
                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        #region DebuffDisarm

        public double DebuffDisarm(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.Debuffs.Values.Where(a => ListDisarm.Contains("[" + a.SpellId + "]")).OrderBy(a => a.TimeLeft)
                        .FirstOrDefault();

                if (longestDebuff == null)
                {
                    return 0;
                }
                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        public double DebuffDisarmCanCleanse(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.Debuffs.Values.Where(a => ListDisarm.Contains("[" + a.SpellId + "]")).OrderBy(a => a.TimeLeft)
                        .FirstOrDefault();

                if (longestDebuff == null || longestDebuff.Spell.DispelType == WoWDispelType.None)
                {
                    return 0;
                }

                Logging.Write("DebuffDisarmCanCleanse: " + longestDebuff.Name + " - " + longestDebuff.SpellId);
                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        #region DebuffRoot

        public double DebuffRoot(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.Debuffs.Values.Where(a => ListRoot.Contains("[" + a.SpellId + "]")).OrderBy(a => a.TimeLeft).
                        FirstOrDefault();

                if (longestDebuff == null)
                {
                    return 0;
                }
                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        public double DebuffRootCanCleanse(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.Debuffs.Values.Where(a => ListRoot.Contains("[" + a.SpellId + "]")).OrderBy(a => a.TimeLeft).
                        FirstOrDefault();

                if (longestDebuff == null || !ListRootCanCleanse.Contains("[" + longestDebuff.SpellId + "]"))
                {
                    return 0;
                }

                Logging.Write("DebuffRootCanCleanse: " + longestDebuff.Name + " - " + longestDebuff.SpellId);
                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        #region DebuffSilence

        public double DebuffSilence(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.Debuffs.Values.Where(a => ListSilence.Contains("[" + a.SpellId + "]")).OrderBy(
                        a => a.TimeLeft)
                        .FirstOrDefault();

                if (longestDebuff == null)
                {
                    return 0;
                }
                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        public double DebuffSilenceCanCleanse(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.Debuffs.Values.Where(a => ListSilence.Contains("[" + a.SpellId + "]")).OrderBy(
                        a => a.TimeLeft)
                        .FirstOrDefault();

                if (longestDebuff == null || !ListSilenceCanCleanse.Contains("[" + longestDebuff.SpellId + "]"))
                {
                    return 0;
                }

                Logging.Write("DebuffRootCanCleanse: " + longestDebuff.Name + " - " + longestDebuff.SpellId);
                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        #region DebuffSnare

        public double DebuffSnare(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.Debuffs.Values.Where(a => ListSnare.Contains("[" + a.SpellId + "]")).OrderBy(a => a.TimeLeft)
                        .
                        FirstOrDefault();

                if (longestDebuff == null)
                {
                    return 0;
                }
                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        public double DebuffSnareCanCleanse(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.Debuffs.Values.Where(a => ListSnare.Contains("[" + a.SpellId + "]")).OrderBy(a => a.TimeLeft)
                        .
                        FirstOrDefault();

                if (longestDebuff == null || longestDebuff.Spell.DispelType == WoWDispelType.None)
                {
                    return 0;
                }

                Logging.Write("DebuffRootCanCleanse: " + longestDebuff.Name + " - " + longestDebuff.SpellId);
                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        #region DebuffDoNotHeal

        public bool DebuffDoNotHeal(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return false;

                bool longestDebuff = target.Debuffs.Values.Any(a => ListHealDoNot.Contains("[" + a.SpellId + "]"));

                return longestDebuff;
            }
        }

        #endregion

        #region DebuffDoNotCleanse

        public bool DebuffDoNotCleanse(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return false;

                foreach (WoWAura aura in target.Debuffs.Values)
                {
                    if (ListCleanseDoNot.Contains("[" + aura.SpellId + "]"))
                    {
                        return true;
                    }
                }
                //var longestDebuff = target.Debuffs.Values.Any(a => ListCleanseDoNot.Contains("[" + a.SpellId + "]"));

                //return longestDebuff;
                return false;
            }
        }

        #endregion

        #region Invulnerable

        public bool Invulnerable(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return false;

                bool longestDebuff = target.GetAllAuras().Any(a => ListImmune.Contains("[" + a.SpellId + "]"));

                return longestDebuff;
            }
        }

        public bool InvulnerablePhysic(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return false;

                bool longestDebuff = target.GetAllAuras().Any(a => ListImmunePhysic.Contains("[" + a.SpellId + "]"));

                return longestDebuff;
            }
        }

        public bool InvulnerableMagic(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return false;

                bool longestDebuff = target.GetAllAuras().Any(a => ListImmuneSpell.Contains("[" + a.SpellId + "]"));

                return longestDebuff;
            }
        }

        #endregion

        #endregion

        #region DoT

        #region DotAll

        public double DotAll(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.GetAllAuras().Where(a => ListDot.Contains("[" + a.SpellId + "]")).OrderBy(
                        a => a.TimeLeft).FirstOrDefault();

                if (longestDebuff == null)
                {
                    return 0;
                }
                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        //#region DoTMagic

        //public double DoTMagic(WoWUnit target)
        //{
        //    if (target == null || !target.IsValid || !target.IsAlive)
        //        return 0;

        //    const string listDebuff =
        //        "Exorcism_879_ Black Arrow_3674_ Explosive Shot_53301_ Moonfire_8921_ Sunfire_93402_ Insect Swarm_5570_ Immolation Trap_13795_ Ignite_12654_ Living Bomb_44457_ Fireball_133_ Frostfire Bolt_44614_ Pyroblast!_92315_ Shadow Word: Pain_589_ Vampiric Touch_34914_ Flame Shock_8050_ Searing Flames_62661_ Immolate_348_ Corruption_172_ Seed of Corruption_27243_ Unstable Affliction_30108_ Censure_31803_";
        //    var longestDebuff =
        //        target.GetAllAuras().Where(a => listDebuff.Contains("_" + a.SpellId + "_")).OrderBy(
        //            a => a.TimeLeft).FirstOrDefault();

        //    if (longestDebuff == null)
        //    {
        //        return 0;
        //    }
        //    return longestDebuff.TimeLeft.TotalMilliseconds;
        //}

        //#endregion

        //#region Curse

        //public double DoTCurse(WoWUnit target)
        //{
        //    if (target == null || !target.IsValid || !target.IsAlive)
        //        return 0;

        //    const string listDebuff = "Curse of Agony_68136_";
        //    var longestDebuff =
        //        target.GetAllAuras().Where(a => listDebuff.Contains("_" + a.SpellId + "_")).OrderBy(
        //            a => a.TimeLeft).FirstOrDefault();

        //    if (longestDebuff == null)
        //    {
        //        return 0;
        //    }
        //    return longestDebuff.TimeLeft.TotalMilliseconds;
        //}

        //#endregion

        //#region DoTDisease

        //public double DoTDisease(WoWUnit target)
        //{
        //    if (target == null || !target.IsValid || !target.IsAlive)
        //        return 0;

        //    const string listDebuff =
        //        "Icy Touch_45477_ Blood Plague_55078_ Frost Fever_55095_ Unholy Blight_49194_ Devouring Plague_2944_";
        //    var longestDebuff =
        //        target.GetAllAuras().Where(a => listDebuff.Contains("_" + a.SpellId + "_")).OrderBy(
        //            a => a.TimeLeft).FirstOrDefault();

        //    if (longestDebuff == null)
        //    {
        //        return 0;
        //    }
        //    return longestDebuff.TimeLeft.TotalMilliseconds;
        //}

        //#endregion

        //#region DoTPhysic

        //public double DoTPhysic(WoWUnit target)
        //{
        //    if (target == null || !target.IsValid || !target.IsAlive)
        //        return 0;

        //    const string listDebuff =
        //        "Rake_1822_ Pounce Bleed_9007_ Rip_1079_ Garrote_703_ Rupture_1943_ Hemorrhage_89775_ Rend_94009_ Deep Wound_12721_ Piercing Shots_63468_ Lacerate_33745_";
        //    var longestDebuff =
        //        target.GetAllAuras().Where(a => listDebuff.Contains("_" + a.SpellId + "_")).OrderBy(
        //            a => a.TimeLeft).FirstOrDefault();

        //    if (longestDebuff == null)
        //    {
        //        return 0;
        //    }
        //    return longestDebuff.TimeLeft.TotalMilliseconds;
        //}

        //#endregion

        //#region DoTPoison

        //public double DoTPoison(WoWUnit target)
        //{
        //    if (target == null || !target.IsValid || !target.IsAlive)
        //        return 0;

        //    const string listDebuff = "Deadly Poison_2818_ Serpent Sting_1978_ Wyvern Sting_19386_";
        //    var longestDebuff =
        //        target.GetAllAuras().Where(a => listDebuff.Contains("_" + a.SpellId + "_")).OrderBy(
        //            a => a.TimeLeft).FirstOrDefault();

        //    if (longestDebuff == null)
        //    {
        //        return 0;
        //    }
        //    return longestDebuff.TimeLeft.TotalMilliseconds;
        //}

        //#endregion

        #endregion

        #region GatherData

        private readonly HashSet<int> _spellIDGather = new HashSet<int>
                                                           {
                                                               11196,
                                                           };

        public List<string> DebuffandCastCollected = new List<string>();

        private string GetCreateClassName(ulong createdbyguid)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                WoWPlayer unitcreateaura = (from unit in ObjectManager.GetObjectsOfType<WoWPlayer>(true, true)
                                            where unit.Guid == createdbyguid
                                            select unit).FirstOrDefault();

                if (unitcreateaura != null && unitcreateaura.IsPlayer)
                {
                    return unitcreateaura.Class.ToString();
                }
                if (unitcreateaura != null && unitcreateaura.IsPet)
                {
                    return unitcreateaura.Class.ToString() + " (Pet)";
                }
            }
            return "";
        }

        public void GatherData()
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                List<WoWUnit> allUnit = ObjectManager.GetObjectsOfType<WoWUnit>(true, true);

                foreach (WoWUnit unit in allUnit)
                {
                    foreach (var aura in unit.Debuffs)
                    {
                        if (!_spellIDGather.Contains(aura.Value.SpellId) &&
                            GetCreateClassName(aura.Value.CreatorGuid) != "")
                        {
                            _spellIDGather.Add(aura.Value.SpellId);
                            //Logging.Write(GetCreateClassName(aura.Value.CreatorGuid) + "|" + "Debuff" + "|" + aura.Value.SpellId + "|" + aura.Value.Name + "|" + aura.Value.Spell.DispelType + "|" + aura.Value.Spell.Mechanic + "|" + aura.Value.Spell.BaseCooldown);
                            DebuffandCastCollected.Add(GetCreateClassName(aura.Value.CreatorGuid) + "|" + "Debuff" + "|" +
                                                       aura.Value.SpellId + "|" + aura.Value.Name + "|" +
                                                       aura.Value.Spell.DispelType + "|" + aura.Value.Spell.Mechanic +
                                                       "|" + aura.Value.Spell.BaseCooldown);
                        }
                    }

                    if (unit.IsCasting && !_spellIDGather.Contains(unit.CastingSpellId) &&
                        GetCreateClassName(unit.Guid) != "")
                    {
                        _spellIDGather.Add(unit.CastingSpellId);
                        //Logging.Write(unit.Class.ToString() + "|" + "Casting" + "|" + unit.CastingSpellId + "|" + unit.CastingSpell.Name + "|" +unit.CastingSpell.DispelType + "|" + unit.CastingSpell.Mechanic + "|" + unit.CastingSpell.BaseCooldown);
                        DebuffandCastCollected.Add(unit.Class.ToString() + "|" + "Casting" + "|" + unit.CastingSpellId +
                                                   "|" + unit.CastingSpell.Name + "|" + unit.CastingSpell.DispelType +
                                                   "|" + unit.CastingSpell.Mechanic + "|" +
                                                   unit.CastingSpell.BaseCooldown);
                    }

                    //foreach (var aura in unit.Buffs)
                    //{
                    //    if (!_spellIDGather.Contains(aura.Value.SpellId))
                    //    {
                    //        _spellIDGather.Add(aura.Value.SpellId);
                    //        Logging.Write("Buff," + aura.Value.SpellId + "," + aura.Value.Name + "," + aura.Value.Spell.DispelType + "," + aura.Value.Spell.Mechanic + "," + aura.Value.Spell.BaseCooldown);
                    //    }
                    //}
                }
            }
        }

        #endregion

        #region GCD

        public DateTime GCDReady;

        //private void UpdateGCDEvent(object sender, LuaEventArgs raw)
        //{
        //    var args = raw.Args;
        //    var player = Convert.ToString(args[0]);

        //    // Not me ... Im out!
        //    if (player != "player")
        //    {
        //        return;
        //    }
        //    var spellID = Convert.ToInt32(args[4]);
        //    var spellName = WoWSpell.FromId(spellID).Name;

        //}

        public void UpdateGCD()
        {
            GCDReady = DateTime.Now + SpellManager.Spells["Stance of the Fierce Tiger"].CooldownTimeLeft;
        }

        public bool GCDL()
        {
            return DateTime.Now + TimeSpan.FromMilliseconds(MyLatency) <= GCDReady;
        }

        public bool Casting()
        {
            return Me.IsCasting && Me.ChanneledCastingSpellId != 115175; //Soothing Mist
        }

        public bool CastingorGCDL()
        {
            return Casting() || GCDL();
        }

        #endregion

        #region GetAsyncKeyState

        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);

        #endregion

        #region GetUnitAuras

        //public double AuraCCDuration;
        //public double AuraCCDurationMax;
        //public WoWAura AuraCC;

        //public double AuraCCBreakonDamageDuration;
        //public double AuraCCBreakonDamageDurationMax;
        //public WoWAura AuraCCBreakonDamage;

        //public double AuraDisarmDuration;
        //public double AuraDisarmDurationMax;
        //public WoWAura AuraDisarm;

        //public double AuraImmuneDuration;
        //public double AuraImmuneDurationMax;
        //public WoWAura AuraImmune;

        //public double AuraImmunePhysicDuration;
        //public double AuraImmunePhysicDurationMax;
        //public WoWAura AuraImmunePhysic;

        //public double AuraImmuneSpellDuration;
        //public double AuraImmuneSpellDurationMax;
        //public WoWAura AuraImmuneSpell;

        //public double AuraRootDuration;
        //public double AuraRootDurationMax;
        //public WoWAura AuraRoot;

        //public double AuraSilenceDuration;
        //public double AuraSilenceDurationMax;
        //public WoWAura AuraSilence;

        //public double AuraSnareDuration;
        //public double AuraSnareDurationMax;
        //public WoWAura AuraSnare;

        //public WoWAura AuraCleanseDoNot;
        //public WoWAura AuraHealDoNot;
        //public int NumberofDebuff;

        //public bool GetUnitAuras(WoWUnit u)
        //{
        //    if (u == null || !u.IsValid || !u.IsAlive)
        //        return false;

        //    AuraCC = null;
        //    AuraCCDuration = 0;
        //    AuraCCDurationMax = 0;

        //    AuraCCBreakonDamage = null;
        //    AuraCCBreakonDamageDuration = 0;
        //    AuraCCBreakonDamageDurationMax = 0;

        //    AuraDisarm = null;
        //    AuraDisarmDuration = 0;
        //    AuraDisarmDurationMax = 0;

        //    AuraImmune = null;
        //    AuraImmuneDuration = 0;
        //    AuraImmuneDurationMax = 0;

        //    AuraImmuneSpell = null;
        //    AuraImmuneSpellDuration = 0;
        //    AuraImmuneSpellDurationMax = 0;

        //    AuraImmunePhysic = null;
        //    AuraImmunePhysicDuration = 0;
        //    AuraImmunePhysicDurationMax = 0;

        //    AuraRoot = null;
        //    AuraRootDuration = 0;
        //    AuraRootDurationMax = 0;

        //    AuraSilence = null;
        //    AuraSilenceDuration = 0;
        //    AuraSilenceDurationMax = 0;

        //    AuraSnare = null;
        //    AuraSnareDuration = 0;
        //    AuraSnareDurationMax = 0;

        //    NumberofDebuff = 0;
        //    AuraCleanseDoNot = null;
        //    AuraHealDoNot = null;

        //    foreach (var aura in u.GetAllAuras())
        //    {
        //        //Count Number of Debuff
        //        if (aura.IsHarmful &&
        //            (aura.Spell.DispelType == WoWDispelType.Disease ||
        //             aura.Spell.DispelType == WoWDispelType.Magic ||
        //             aura.Spell.DispelType == WoWDispelType.Poison))
        //        {
        //            NumberofDebuff = NumberofDebuff + 1;
        //        }

        //        //Find out if AuraCleanseDoNot exits
        //        if (ListCleanseDoNot.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraCleanseDoNot = aura.;
        //        }

        //        //Find out if AuraHealDoNot exits
        //        if (ListHealDoNot.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraHealDoNot = aura.;
        //        }

        //        if (ListCC.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraCCDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraCCDuration > AuraCCDurationMax)
        //            {
        //                AuraCC = aura.;
        //                AuraCCDurationMax = AuraCCDuration;
        //            }
        //        }

        //        if (ListCCBreakonDamage.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraCCBreakonDamageDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraCCBreakonDamageDuration > AuraCCBreakonDamageDurationMax)
        //            {
        //                AuraCCBreakonDamage = aura.;
        //                AuraCCBreakonDamageDurationMax = AuraCCBreakonDamageDuration;
        //            }
        //        }

        //        if (ListDisarm.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraDisarmDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraDisarmDuration > AuraDisarmDurationMax)
        //            {
        //                AuraDisarm = aura.;
        //                AuraDisarmDurationMax = AuraDisarmDuration;
        //            }
        //        }

        //        if (ListImmune.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraImmuneDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraImmuneDuration > AuraImmuneDurationMax)
        //            {
        //                AuraImmune = aura.;
        //                AuraImmuneDurationMax = AuraImmuneDuration;
        //            }
        //        }

        //        if (ListImmuneSpell.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraImmuneSpellDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraImmuneSpellDuration > AuraImmuneSpellDurationMax)
        //            {
        //                AuraImmuneSpell = aura.;
        //                AuraImmuneSpellDurationMax = AuraImmuneSpellDuration;
        //            }
        //        }

        //        if (ListImmunePhysic.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraImmunePhysicDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraImmunePhysicDuration > AuraImmunePhysicDurationMax)
        //            {
        //                AuraImmunePhysic = aura.;
        //                AuraImmunePhysicDurationMax = AuraImmunePhysicDuration;
        //            }
        //        }

        //        if (ListRoot.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraRootDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraRootDuration > AuraRootDurationMax)
        //            {
        //                AuraRoot = aura.;
        //                AuraRootDurationMax = AuraRootDuration;
        //            }
        //        }

        //        if (ListSilence.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraSilenceDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraSilenceDuration > AuraSilenceDurationMax)
        //            {
        //                AuraSilence = aura.;
        //                AuraSilenceDurationMax = AuraSilenceDuration;
        //            }
        //        }

        //        if (ListSnare.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraSnareDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraSnareDuration > AuraSnareDurationMax)
        //            {
        //                AuraSnare = aura.;
        //                AuraSnareDurationMax = AuraSnareDuration;
        //            }
        //        }
        //    }
        //    return true;
        //}

        #endregion

        #region CountEneyNeary

        private double CountEneyNeary(WoWObject unitCenter, float distance)
        {
            return
                NearbyUnFriendlyUnits.Where(
                    unit =>
                    unitCenter.Location.Distance(unit.Location) <= distance &&
                    unit.Combat && !unit.IsPet &&
                    (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
                     unit.IsTargetingMeOrPet)).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        #endregion

        #region CountEnemyFromPoint

        //private double CountEnemyFromPoint(WoWPoint pointCenter, float radius)
        //{
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            pointCenter.Distance(unit.Location) <= radius &&
        //            unit.Combat).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CountFriendlyNearyNeedHeal

        private double CountFriendlyNearyNeedHeal(WoWObject unitCenter, float distance)
        {
            return
                NearbyFriendlyPlayers.Where(
                    unit =>
                    unitCenter.Location.Distance(unit.Location) <= distance &&
                    unit.HealthPercent < THSettings.Instance.SDoNotHealAbove).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        private double CountFriendlyNearyNeedHeal(WoWObject unitCenter, float distance, double healthPercnet)
        {
            return
                NearbyFriendlyPlayers.Where(
                    unit =>
                    unitCenter.Location.Distance(unit.Location) <= distance &&
                    unit.HealthPercent <= healthPercnet).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        private double CountFriendlyNearyNeedHealSpinningCraneKick(WoWObject unitCenter, float distance)
        {
            return
                NearbyFriendlyPlayers.Where(
                    unit =>
                    unitCenter.Location.Distance(unit.Location) <= distance &&
                    unit.HealthPercent < THSettings.Instance.SSpinCraneKickHeal).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        private double CountFriendlyNearyNeedHealChiBurst(WoWObject unitCenter, float distance)
        {
            return
                NearbyFriendlyPlayers.Where(
                    unit =>
                    unitCenter.Location.Distance(unit.Location) <= distance &&
                    unit.HealthPercent < THSettings.Instance.SChiBurstHeal).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        private double CountFriendlyNearyNeedHealChiTorpedo(WoWObject unitCenter, float distance)
        {
            return
                NearbyFriendlyPlayers.Where(
                    unit =>
                    unitCenter.Location.Distance(unit.Location) <= distance &&
                    unit.HealthPercent < THSettings.Instance.SChiTorpedo).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        private double CountFriendlyNearyNeedHealRevive()
        {
            return
                NearbyFriendlyPlayers.Where(
                    unit =>
                    //unitCenter.Location.Distance(unit.Location) <= distance &&
                    unit.HealthPercent < THSettings.Instance.SRevival).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }


        //private double CountFriendlyNeary(WoWObject unitCenter, float distance)
        //{
        //    return
        //        NearbyFriendlyPlayers.Where(
        //            unit =>
        //            unitCenter.Location.Distance(unit.Location) <= distance).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region GetMyStatue

        public DateTime LastDropStatueAttempt = DateTime.Now;
        public WoWObject MyStatue;
        //public WoWPoint LastStatueLocation = Me.Location;
        public WoWPoint LastStatueLocation;

        public bool GetMyStatue()
        {
            //MyStatue =
            //    ObjectManager.GetObjectsOfType<WoWObject>(true, true).FirstOrDefault(
            //        o => o.Location.Distance(LastStatueLocation) < 3 && o.Name.Contains("Statue"));

            MyStatue = (from unit in NearbyFriendlyUnits
                        where unit.Name == "Jade Serpent Statue" || unit.Name == "Black Ox Statue"
                        select unit).FirstOrDefault();
            //if (MyStatue != null)
            //{
            //    Logging.Write(LogLevel.Diagnostic, "Me.Guid: " + Me.Guid);
            //    Logging.Write(LogLevel.Diagnostic, "MyStatue.Guid: " + MyStatue.Guid);
            //    Logging.Write(LogLevel.Diagnostic, "MyStatue.DescriptorGuid: " + MyStatue.DescriptorGuid);
            //    Logging.Write(LogLevel.Diagnostic, "MyStatue.Location: " + MyStatue.Location);
            //    Logging.Write(LogLevel.Diagnostic, "LastStatueLocation: " + LastStatueLocation);
            //}
            return MyStatue != null;
        }

        #endregion

        #region CountUnitUplift

        private double CountUnitUplift()
        {
            return
                NearbyFriendlyPlayers.Where(
                    unit =>
                    MyAuraTimeLeft(119611, Me) > 0 &&
                    unit.HealthPercent < THSettings.Instance.SUplift).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }


        //private double CountUnitUpliftChiDump()
        //{
        //    return
        //        NearbyFriendlyPlayers.Where(
        //            unit =>
        //            MyAuraTimeLeft(119611, Me) > 0 &&
        //            unit.HealthPercent < THSettings.Instance.SDoNotHealAbove).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region GetAllMyAuras

        public DateTime LastGetAllMyAuras = DateTime.Now;

        public void DumpAuras()
        {
            if (LastGetAllMyAuras.AddSeconds(10) < DateTime.Now)
            {
                var i = 1;
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");
                foreach (var aura in Me.GetAllAuras())
                {
                    Logging.Write(LogLevel.Diagnostic,
                                  i + ". Me.GetAllAuras Name: " + aura.Name + " - SpellId: " + aura.SpellId);
                    i = i + 1;
                }
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");

                i = 1;
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");
                foreach (var aura in Me.Auras)
                {
                    Logging.Write(LogLevel.Diagnostic,
                                  i + ". Me.Auras - Name: " + aura.Value.Name + " - SpellId: " + aura.Value.SpellId);
                    i = i + 1;
                }
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");

                i = 1;
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");
                foreach (var aura in Me.ActiveAuras)
                {
                    Logging.Write(LogLevel.Diagnostic,
                                  i + ". Me.ActiveAuras - Name: " + aura.Value.Name + " - SpellId: " +
                                  aura.Value.SpellId);
                    i = i + 1;
                }
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");

                i = 1;
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");
                foreach (var aura in Me.PassiveAuras)
                {
                    Logging.Write(LogLevel.Diagnostic,
                                  i + ". Me.PassiveAuras - Name: " + aura.Value.Name + " - SpellId: " +
                                  aura.Value.SpellId);
                    i = i + 1;
                }
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");

                LastGetAllMyAuras = DateTime.Now;
            }
        }

        #endregion

        #region GetUnitChiTorpedo

        public WoWUnit UnitChiTorpedo;

        private bool GetUnitChiTorpedo()
        {
            UnitChiTorpedo = null;
            UnitChiTorpedo = (from unit in NearbyFriendlyUnits
                              where unit != Me
                              where unit.Combat
                              where unit.Distance > 5
                              where unit.Distance < 12
                              where
                                  CountFriendlyNearyNeedHealChiTorpedo(unit, 10) >= THSettings.Instance.SChiTorpedoUnit
                              where unit.InLineOfSight
                              orderby CountFriendlyNearyNeedHealChiTorpedo(unit, 10)
                              select unit).FirstOrDefault();
            return UnitChiTorpedo != null;
        }

        #endregion

        #region GetUnitUnitLeeroftheOx

        public WoWUnit UnitLeeroftheOx;

        private bool GetUnitUnitLeeroftheOx()
        {
            UnitLeeroftheOx = null;
            UnitLeeroftheOx = (from unit in NearbyUnFriendlyUnits
                               //try to bring the low hp guy (high threat by dps to me)
                               orderby unit.HealthPercent ascending
                               where Me.Combat
                               where Me.Level >= 78
                               //Only Level 78 or up
                               where HasGlyph.Contains("Glyph of Leer of the Ox")
                               where Me.CurrentMap.IsDungeon || Me.CurrentMap.IsRaid
                               where unit.Combat && !unit.Fleeing
                               where unit.ThreatInfo.RawPercent < 100
                               where (unit.IsTargetingMyPartyMember ||
                                      unit.IsTargetingMyRaidMember ||
                                      unit.IsTargetingMeOrPet && Me.HealthPercent < THSettings.Instance.SUrgentHeal)
                               //Make sure dont taunt off another tank
                               where !unit.CurrentTarget.HasAura("Vengeance")
                               //make sure under 40 yard
                               where Me.HasAura("Sanctuary of the Ox")
                               //where LastBlackOxStatueLocation != null //Don't need because Me.HasAura("Sanctuary of the Ox")
                               where Me.Location.Distance(LastStatueLocation) < 40
                               where unit.Distance <= 40
                               where unit.InLineOfSpellSight
                               select unit).FirstOrDefault();
            return UnitLeeroftheOx != null;
        }

        #endregion

        #region GetUnitBreathofFire

        public WoWUnit UnitBreathofFire;

        private double CountUnitBreathofFire(WoWUnit unitCenter)
        {
            return
                NearbyUnFriendlyUnits.Where(
                    unit =>
                    unit.Combat &&
                    unit.HasAura("Dizzying Haze") &&
                    MyAuraTimeLeft("Breath of Fire", unit) <= 1000 &&
                    (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
                     unit.IsTargetingMeOrPet) &&
                    (unit.IsWithinMeleeRange || unit.Distance <= 8) &&
                    unitCenter.Location.Distance(unit.Location) <= 8).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        private bool GetUnitBreathofFire()
        {
            UnitBreathofFire = null;
            UnitBreathofFire = (from unit in NearbyUnFriendlyUnits
                                where unit.Distance <= 8
                                where unit.Combat
                                where unit.GotTarget
                                where unit.CurrentTarget != Me
                                where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
                                       unit.IsTargetingMeOrPet)
                                where CountUnitBreathofFire(unit) >= 1
                                orderby CountUnitBreathofFire(unit) descending
                                select unit).FirstOrDefault();
            return UnitBreathofFire != null;
        }

        #endregion

        #region GetUnitChiBurstHeal

        public WoWUnit UnitChiBurstHeal;

        private bool GetUnitChiBurstHeal()
        {
            UnitChiBurstHeal = null;
            UnitChiBurstHeal = (from unit in NearbyFriendlyUnits
                                where unit != Me
                                where unit.Combat
                                where CountFriendlyNearyNeedHealChiBurst(unit, 8) >= 3
                                orderby CountFriendlyNearyNeedHeal(unit, 10) descending
                                select unit).FirstOrDefault();
            return UnitChiBurstHeal != null;
        }

        #endregion

        #region GetUnitChiBurstAttack

        public WoWUnit UnitChiBurstAttack;

        //private bool GetUnitChiBurstAttack()
        //{
        //    UnitChiBurstAttack = null;
        //    UnitChiBurstAttack = (from unit in NearbyUnFriendlyUnits
        //                          where unit.Combat
        //                          where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
        //                                 unit.IsTargetingMeOrPet)
        //                          where AttackableValid(unit)
        //                          orderby CountEneyNeary(unit, 10) descending
        //                          select unit).FirstOrDefault();
        //    return UnitChiBurstAttack != null;
        //}

        #endregion

        #region GetUnitChiWavetAttack

        public WoWUnit UnitChiWavetAttack;

        //private bool GetUnitChiWavetAttack()
        //{
        //    UnitChiWavetAttack = null;
        //    UnitChiWavetAttack = (from unit in NearbyUnFriendlyUnits
        //                          where unit.Combat
        //                          where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
        //                                 unit.IsTargetingMeOrPet)
        //                          where AttackableValid(unit)
        //                          orderby CountEneyNeary(unit, 20) descending
        //                          select unit).FirstOrDefault();
        //    return UnitChiWavetAttack != null;
        //}

        #endregion

        #region GetUnitZenSphere

        public WoWUnit UnitZenSphere;

        private bool GetUnitZenSphere()
        {
            UnitZenSphere = null;
            UnitZenSphere = (from unit in NearbyFriendlyPlayers
                             where MyAura("Zen Sphere", unit)
                             select unit).FirstOrDefault();


            //Make Zen Sphere Detonate
            if (UnitZenSphere != null &&
                (CountFriendlyNearyNeedHeal(UnitZenSphere, 10, THSettings.Instance.SDoNotHealAbove) >= 3 ||
                 UnitZenSphere.HealthPercent < THSettings.Instance.SPriorityHeal))
            {
                return true;
            }

            //Switch Zen Sphere is needed
            if (UnitZenSphere != null && UnitHeal != null && UnitHeal.HealthPercent < THSettings.Instance.SZenSphere &&
                UnitZenSphere.HealthPercent - 10 > UnitHeal.HealthPercent)
            {
                UnitZenSphere = UnitHeal;
                return true;
            }

            //Find Friendly unit to Zen Sphere, Attack is just a wast of Chi, not healer job anyway
            if (UnitZenSphere == null && UnitHeal != null && UnitHeal.HealthPercent < THSettings.Instance.SZenSphere)
            {
                UnitZenSphere = UnitHeal;
            }
            return UnitZenSphere != null;
        }

        #endregion

        #region GetUnitZenSphereApplyNew

        public WoWUnit UnitZenSphereApplyNew;

        //private bool GetUnitZenSphereApplyNew()
        //{
        //    UnitZenSphereApplyNew = null;
        //    UnitZenSphereApplyNew = (from unit in NearbyFriendlyUnits
        //                             where unit.Combat
        //                             where CountEneyNeary(unit, 10) >= 3
        //                             orderby CountEneyNeary(unit, 10) descending
        //                             orderby unit.HealthPercent ascending
        //                             select unit).FirstOrDefault();
        //    return UnitZenSphereApplyNew != null;
        //}

        #endregion

        #region GetUnitDizzyingHaze

        public WoWUnit UnitDizzyingHaze;

        private bool GetUnitDizzyingHaze()
        {
            UnitDizzyingHaze = null;
            UnitDizzyingHaze = (from unit in NearbyUnFriendlyUnits
                                where !Blacklist.Contains(unit.Guid)
                                where Me.Combat
                                where Me.CurrentMap.IsDungeon || Me.CurrentMap.IsRaid
                                where unit.Combat
                                //Make sure dont aggro extra group
                                where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember)
                                //where !unit.IsTargetingMeOrPet
                                where unit.ThreatInfo.RawPercent < 100
                                where !unit.CurrentTarget.HasAura("Vengeance")
                                where unit.Distance <= 40
                                where !unit.HasAura("DizzyingHaze")
                                where unit.InLineOfSpellSight
                                select unit).FirstOrDefault();
            return UnitDizzyingHaze != null;
        }

        #endregion

        #region GetUnitKegSmash

        public WoWUnit UnitKegSmash;

        //private double CountUnitKegSmash(WoWUnit unitCenter)
        //{
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            //unitCenter.Combat && unitCenter.CurrentTarget == Me &&
        //            unit.Combat &&
        //            (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
        //             unit.IsTargetingMeOrPet) &&
        //            unit.Distance <= 8 &&
        //            unitCenter.Location.Distance(unit.Location) <= 8).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        //private bool GetUnitKegSmash()
        //{
        //    UnitKegSmash = null;
        //    UnitKegSmash = (from unit in NearbyUnFriendlyUnits
        //                    where unit.Distance <= 8
        //                    where unit.Combat
        //                    where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
        //                           unit.IsTargetingMeOrPet)
        //                    where CountUnitKegSmash(unit) >= 2 || !unit.HasAura("Weakened Blows")
        //                    orderby CountUnitKegSmash(unit) descending
        //                    select unit).FirstOrDefault();
        //    return UnitKegSmash != null;
        //}

        #endregion

        #region GetUnitLowThreat

        public WoWUnit UnitLowThreat;

        private bool GetUnitLowThreat()
        {
            UnitLowThreat = null;
            UnitLowThreat = (from unit in NearbyUnFriendlyUnits
                             orderby unit.ThreatInfo.RawPercent ascending
                             where Me.Combat
                             where Me.CurrentMap.IsDungeon || Me.CurrentMap.IsRaid
                             where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
                                    unit.IsTargetingMeOrPet)
                             where unit.IsWithinMeleeRange
                             select unit).FirstOrDefault();
            return UnitLowThreat != null;
        }

        #endregion

        #region GetUnitProvoke

        public WoWUnit UnitProvoke;

        private bool GetUnitProvoke()
        {
            UnitProvoke = null;
            UnitProvoke = (from unit in NearbyUnFriendlyUnits
                           where Me.Combat
                           where Me.CurrentMap.IsDungeon || Me.CurrentMap.IsRaid
                           where unit.Combat && !unit.Fleeing
                           where unit.ThreatInfo.RawPercent < 100
                           where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember)
                           where !unit.IsTargetingMeOrPet
                           //Make sure dont taunt off another tank
                           where !unit.CurrentTarget.HasAura("Vengeance")
                           where unit.Distance <= 40
                           where unit.InLineOfSpellSight
                           select unit).FirstOrDefault();
            return UnitProvoke != null;
        }

        #endregion

        #region GetUnitRenewingMist

        public WoWUnit UnitRenewingMist;

        private bool GetUnitRenewingMist()
        {
            UnitRenewingMist = null;
            UnitRenewingMist = (from unit in NearbyFriendlyUnits
                                where !Blacklist.Contains(unit.Guid)
                                orderby MyAuraTimeLeft(119611, Me) ascending
                                //where Me.IsInInstance
                                where unit.Combat
                                where unit.HealthPercent <= THSettings.Instance.SRenewingMist
                                //where unit.IsPlayer || Me.CurrentMap.IsArena && (unit.IsPlayer || unit.IsPet)
                                //where MyAuraTimeLeft(119611, Me) <= MyLatency
                                where HealableValid(unit)
                                select unit).FirstOrDefault();
            return UnitRenewingMist != null;
        }

        #endregion

        #region GetUnitSoothingMist

        public WoWUnit UnitSoothingMist;

        private bool GetUnitSoothingMist()
        {
            UnitSoothingMist = null;
            UnitSoothingMist = (from unit in NearbyFriendlyUnits
                                where MyAuraTimeLeft("Soothing Mist", unit) > MyLatency
                                select unit).FirstOrDefault();
            return UnitSoothingMist != null;
        }

        #endregion

        #region GetUnitUplift

        //public WoWUnit UnitUplift;

        //private bool GetUnitUplift()
        //{
        //    UnitUplift = null;
        //    UnitUplift = (from unit in NearbyFriendlyUnits
        //                  where MyAuraTimeLeft(119611, Me) > MyLatency
        //                  select unit).FirstOrDefault();
        //    return UnitUplift != null;
        //}

        #endregion

        #region IsSafeForZenMediation

        public WoWUnit UnitCanBreakZenMediation;

        #endregion

        #region Healable

        public bool Healable(WoWUnit u)
        {
            if (ValidUnit(u) && u.Distance < 40 && !IsEnemy(u) && !DebuffDoNotHeal(u) && u.InLineOfSpellSight)
            {
                return true;
            }
            return false;
        }

        //prevent double ValidUnit Check
        public bool HealableValid(WoWUnit u)
        {
            if (u.Distance < 40 && !IsEnemy(u) && !DebuffDoNotHeal(u) && u.InLineOfSpellSight)
            {
                return true;
            }
            return false;
        }

        public bool Healable60(WoWUnit u)
        {
            if (ValidUnit(u) && u.Distance < 60 && !IsEnemy(u) && !DebuffDoNotHeal(u) && u.InLineOfSpellSight)
            {
                return true;
            }
            return false;
        }

        //prevent double ValidUnit Check
        public bool Healable60Valid(WoWUnit u)
        {
            if (u.Distance < 60 && !IsEnemy(u) && !DebuffDoNotHeal(u) && u.InLineOfSpellSight)
            {
                return true;
            }
            return false;
        }

        #endregion

        #region IndexToKeys

        public Keys KeyTwo;

        public Keys IndexToKeys(int index)
        {
            switch (index)
            {
                case 1:
                    return Keys.A;
                case 2:
                    return Keys.B;
                case 3:
                    return Keys.C;
                case 4:
                    return Keys.D;
                case 5:
                    return Keys.E;
                case 6:
                    return Keys.F;
                case 7:
                    return Keys.G;
                case 8:
                    return Keys.H;
                case 9:
                    return Keys.I;
                case 10:
                    return Keys.I;
                case 11:
                    return Keys.K;
                case 12:
                    return Keys.L;
                case 13:
                    return Keys.M;
                case 14:
                    return Keys.N;
                case 15:
                    return Keys.O;
                case 16:
                    return Keys.P;
                case 17:
                    return Keys.Q;
                case 18:
                    return Keys.R;
                case 19:
                    return Keys.S;
                case 20:
                    return Keys.T;
                case 21:
                    return Keys.U;
                case 22:
                    return Keys.V;
                case 23:
                    return Keys.W;
                case 24:
                    return Keys.X;
                case 25:
                    return Keys.Y;
                case 26:
                    return Keys.Z;
                case 27:
                    return Keys.Up;
                case 28:
                    return Keys.Down;
                case 29:
                    return Keys.Left;
                case 30:
                    return Keys.Right;
            }
            return Keys.None;
        }

        #endregion

        #region InterruptCast

        public double InterruptCastNoChannel(WoWUnit target)
        {
            double timeLeft = 0;

            if (target != null && target.IsCasting && ListCastSpellInterrupt.Contains("[" + target.CastingSpellId + "]"))
            {
                timeLeft = target.CurrentCastTimeLeft.TotalMilliseconds;
            }
            return timeLeft;
        }

        //public double OffensiveCastNoChannel(WoWUnit target)
        //{
        //    double timeLeft = 0;

        //    const string spellNoChanneled = "[30451]=Arcane Blast [33786]=Cyclone [421]=Chain Lightning [50796]=Chaos Bolt [339]Entangling Roots [5782]=Fear [133]=Fireball [116]=Frostbolt [44614]=Frostfire Bolt [71521]=Hand of Gul'dan [48181]=Haunt [51514]=Hex [14914]=Holy Fire [348]=Immolate [29722]=Incinerate [51505]=Lava Burst [403=Lightning Bolt [8129]=Mana Burn [8092]=Mind Blast [605]=Mind Control [73510]=Mind Spike [118][28272][61721][61305][61780][28271]=Polymorph [11366]=Pyroblast [2948=]Scorch [5676]=Searing Pain [27243]=Seed of Corruption [686]=Shadow Bolt [585]=Smite [6353]=Soul Fire [2912]=Starfire [78674]=Starsurge [30108]=Unstable Affliction [5176]=Wrath [34914]=Vampiric Touch";

        //    if (target != null && target.IsCasting && spellNoChanneled.Contains("[" + target.CastingSpellId + "]"))
        //    {
        //        timeLeft = target.CurrentCastTimeLeft.TotalMilliseconds;
        //    }
        //    return timeLeft;
        //}

        public double InterruptCastChannel(WoWUnit target)
        {
            double timeLeft = 0;

            if (target != null && target.IsCasting &&
                ListChannelSpellsInterrupt.Contains("[" + target.CastingSpellId + "]"))
            {
                timeLeft = 111;
            }
            return timeLeft;
        }

        //public double OffensiveCastChannel(WoWUnit target)
        //{
        //    double timeLeft = 0;
        //    const string spellChanneled = "[689]=Drain Life [879]=Exorcism [1120]=Drain Soul [5143]=Arcane Missiles [15407]=Mind Flay [89420]=Drain Life";

        //    if (target != null && target.IsCasting && spellChanneled.Contains("_" + target.CastingSpellId + "_"))
        //    {
        //        timeLeft = 111;
        //    }
        //    return timeLeft;
        //}

        #endregion

        #region IsHealing

        //private static bool IsHealing()
        //{
        //    return Me.IsCasting &&
        //           (Me.CastingSpell.Name == "Flash of Light" || Me.CastingSpell.Name == "Divine Light" ||
        //            Me.CastingSpell.Name == "Holy Light" || Me.CastingSpell.Name == "Holy Radiance");
        //}

        #endregion

        #region IsAttacking

        //private static bool IsAttacking()
        //{
        //    return Me.IsCasting && Me.CastingSpell.Name == "Denounce";
        //}

        #endregion

        #region IsEnemy

        //public ulong RealGuid;

        //private static WoWPlayer GetUnitIsInMyPartyOrRaid(WoWUnit u)
        //{
        //    using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return (from unit in ObjectManager.GetObjectsOfType<WoWPlayer>(true, true)
        //                where unit.IsInMyPartyOrRaid
        //                //|| unit.IsMe && (!Me.IsInParty || !Me.IsInRaid)
        //                where unit.Guid == u.Guid || unit.Guid == u.CreatedByUnitGuid
        //                select unit).FirstOrDefault();
        //    }
        //}


        public bool IsEnemy(WoWUnit target)
        {
            if (target == null)
            {
                return false;
            }

            if (!target.IsFriendly || target.Name.Contains("Dummy") && target.IsWithinMeleeRange)
            {
                return true;
            }
            return false;
        }

        public bool IsMyPartyRaidMember(WoWUnit u)
        {
            if (u == null || !u.IsValid)
            {
                return false;
            }

            if (u.IsPet || u.IsTotem)
            {
                if (Me.PartyMembers.Contains(u.CreatedByUnit) || Me.RaidMembers.Contains(u.CreatedByUnit))
                {
                    return true;
                }
            }
            else if (u.IsPlayer)
            {
                if (Me.PartyMembers.Contains(u) || Me.RaidMembers.Contains(u))
                {
                    return true;
                }
            }

            return false;
        }

        #endregion

        #region IsMeorFocus

        public bool IsMeorFocus(WoWUnit target)
        {
            if (target == Me ||
                target == Me.FocusedUnit && ValidUnit(Me.FocusedUnit) && !IsEnemy(Me.FocusedUnit) ||
                target == Me.CurrentTarget && ValidUnit(Me.CurrentTarget) && !IsEnemy(Me.CurrentTarget) ||
                Me.CurrentMap.IsArena)
            {
                return true;
            }
            return false;
        }

        #endregion

        #region MeIsTank

        public static bool MeIsTank
        {
            get
            {
                //return (StyxWoW.Me.Role & WoWPartyMember.GroupRole.Tank) != 0 ||
                //        Tanks.All(t => !t.IsAlive) && StyxWoW.Me.HasAura("Bear Form");
                return (StyxWoW.Me.Role & WoWPartyMember.GroupRole.Tank) != 0;
            }
        }

        #endregion

        #region MyAura

        public bool MyAura(string auraName, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return false;

                bool aura = u.GetAllAuras().Any(a => a.Name == auraName && a.CreatorGuid == Me.Guid);

                return aura;
                //return u.ActiveAuras.Any(a => a.Value.Name == auraName && a.Value.CreatorGuid == Me.Guid);
            }
        }


        public bool MyAura(int auraID, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return false;

                bool aura = u.GetAllAuras().Any(a => a.SpellId == auraID && a.CreatorGuid == Me.Guid);

                return aura;

                //return u.ActiveAuras.Any(a => a.Value.SpellId == auraID && a.Value.CreatorGuid == Me.Guid);
            }
        }

        #endregion

        #region MyAuraTimeLeft

        public double MyAuraTimeLeft(string auraName, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        public double MyAuraTimeLeft(int auraID, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        #region UnitAuraTimeLeft

        public double UnitAuraTimeLeft(string auraName, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == u.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        public double UnitAuraTimeLeft(int auraID, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == u.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        #region MyAuraStackCount

        public double MyAuraStackCount(string auraName, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == u.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.StackCount;
            }
        }

        public double MyAuraStackCount(int auraID, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == u.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.StackCount;
            }
        }

        #endregion

        #region ReadXML

        public static string ListAllCanCleanseDebuff;
        public string ListCC;
        public string ListCCBreakonDamage;
        public string ListCCCanCleanse;
        public string ListCastSpellInterrupt;
        public string ListChannelSpellsInterrupt;
        public string ListCleanseASAP;
        public string ListCleanseDoNot;
        public string ListDisarm;
        public string ListDisarmCanCleanse;
        public string ListDot;
        public string ListDotCanCleanse;
        public string ListHealDoNot;
        public string ListImmune;
        public string ListImmunePhysic;
        public string ListImmuneSpell;
        public string ListRoot;
        public string ListRootCanCleanse;
        public string ListSilence;
        public string ListSilenceCanCleanse;
        public string ListSnare;
        public string ListSnareCanCleanse;

        public bool ReadNextXMLData;
        public XmlTextReader XmlReader;

        public void ReadXML()
        {
            #region DataSourceXML

            //Get Cast Spells to Interrupt to String
            ListCastSpellInterrupt = "";
            XmlReader = new XmlTextReader(THSettings.Instance.PathCastSpells);
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListCastSpellInterrupt = ListCastSpellInterrupt + "[" +
                                             XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get Channel Spells to Interrupt to String
            ListChannelSpellsInterrupt = "";
            XmlReader = new XmlTextReader(THSettings.Instance.PathChannelSpells);
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListChannelSpellsInterrupt =
                        ListChannelSpellsInterrupt + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListCleanseASAP to String
            ListCleanseASAP = "";
            XmlReader = new XmlTextReader(THSettings.Instance.PathCleanseASAP);
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListCleanseASAP =
                        ListCleanseASAP + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListCleanseDoNot to String
            ListCleanseDoNot = "";
            XmlReader = new XmlTextReader(THSettings.Instance.PathCleanseDoNot);
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListCleanseDoNot =
                        ListCleanseDoNot + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListHealDoNot to String
            ListHealDoNot = "";
            XmlReader = new XmlTextReader(THSettings.Instance.PathHealDoNot);
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListHealDoNot = ListHealDoNot + "[" + XmlReader.Value + "] ";
                    //ListHealDoNot.Add(XmlReader.Value);
                    //ListCC = XmlReader.Value;
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            #endregion

            #region Debuff XML

            //Get ListCC to String
            ListCC = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListCC.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListCC = ListCC + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListCCCanCleanse to String
            ListCCCanCleanse = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListCCCanCleanse.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListCCCanCleanse = ListCCCanCleanse + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListCCBreakonDamage to String
            ListCCBreakonDamage = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListCCBreakonDamage.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListCCBreakonDamage = ListCCBreakonDamage + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListDisarm to String
            ListDisarm = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListDisarm.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListDisarm = ListDisarm + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListDisarmCanCleanse to String
            ListDisarmCanCleanse = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListDisarmCanCleanse.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListDisarmCanCleanse = ListDisarmCanCleanse + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListDot to String
            ListDot = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListDot.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListDot = ListDot + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListDotCanCleanse to String
            ListDotCanCleanse = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListDotCanCleanse.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListDotCanCleanse = ListDotCanCleanse + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListImmune to String
            ListImmune = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListImmune.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListImmune = ListImmune + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListImmuneSpell to String
            ListImmuneSpell = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListImmuneSpell.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListImmuneSpell = ListImmuneSpell + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListImmunePhysic to String
            ListImmunePhysic = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListImmunePhysic.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListImmunePhysic = ListImmunePhysic + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListRoot to String
            ListRoot = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListRoot.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListRoot = ListRoot + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListRootCanCleanse to String
            ListRootCanCleanse = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListRootCanCleanse.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListRootCanCleanse = ListRootCanCleanse + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListSilence to String
            ListSilence = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListSilence.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListSilence = ListSilence + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListSilenceCanCleanse to String
            ListSilenceCanCleanse = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListSilenceCanCleanse.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListSilenceCanCleanse = ListSilenceCanCleanse + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListSnare to String
            ListSnare = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListSnare.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListSnare = ListSnare + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            //Get ListSnareCanCleanse to String
            ListSnareCanCleanse = "";
            XmlReader = new XmlTextReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                                                       string.Format(
                                                           @"Routines/TuanHAMonk/THListSnareCanCleanse.xml")));
            while (XmlReader.Read())
            {
                if (XmlReader.NodeType == XmlNodeType.Element && XmlReader.Name == "SID")
                {
                    ReadNextXMLData = true;
                }
                if (XmlReader.NodeType == XmlNodeType.Text && ReadNextXMLData)
                {
                    ListSnareCanCleanse = ListSnareCanCleanse + "[" + XmlReader.Value + "] ";
                    ReadNextXMLData = false;
                }
            }
            XmlReader.Close();

            ListAllCanCleanseDebuff = ListDotCanCleanse + ListCCCanCleanse + ListRootCanCleanse + ListSilenceCanCleanse +
                                      ListSnareCanCleanse + ListDisarmCanCleanse;

            #endregion

            #region Log

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("List Spells Cleanse ASAP: " + ListCleanseASAP);

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("List Spells Do Not Cleanse: " + ListCleanseDoNot);

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("List Spells Do Not Heal: " + ListHealDoNot);

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("List Cast Spells to Interrupt: " + ListCastSpellInterrupt);

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("List Channel Spells to Interrupt: " + ListChannelSpellsInterrupt);

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("ListCC: " + ListCC);

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("ListDisarm: " + ListDisarm);

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("ListImmune: " + ListImmune);

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("ListImmuneSpell: " + ListImmuneSpell);

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("ListImmunePhysic: " + ListImmunePhysic);

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("ListRoot: " + ListRoot);

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("ListSilence: " + ListSilence);

            //Logging.Write("");
            //Logging.Write("----------------------------------");
            //Logging.Write("ListSnare: " + ListSnare);

            #endregion
        }

        #endregion

        #region RestRotation

        public Composite RestRotation()
        {
            return
                // Don't fucking run the rest behavior (or any other) if we're dead or a ghost. Thats all.
                new Decorator(
                    ret => !Me.IsMoving && !Me.IsDead && !Me.IsGhost && !Me.IsCasting && !IsOverrideModeOn,
                    new PrioritySelector(
                        new Decorator(
                            ret =>
                            SpellManager.HasSpell("Stance of the Wise Serpent") &&
                            Me.ManaPercent < THSettings.Instance.SFood &&
                            !Me.IsSwimming && Me.ManaPercent <= THSettings.Instance.SStartEating &&
                            !Me.HasAura("Drink") && Consumable.GetBestDrink(false) != null && !Me.IsCasting,
                            new PrioritySelector(
                                new Decorator(
                                    new Action(delegate
                                                   {
                                                       Thread.Sleep(TimeSpan.FromMilliseconds(300));

                                                       if (!Me.HasAura("Drink"))
                                                       {
                                                           Styx.CommonBot.Rest.DrinkImmediate();
                                                           StyxWoW.SleepForLagDuration();
                                                       }

                                                       if (Me.HasAura("Drink") &&
                                                           Me.ManaPercent <
                                                           THSettings.Instance.SDoNotHealAbove &&
                                                           !Me.Combat)
                                                       {
                                                           return RunStatus.Running;
                                                       }
                                                       return RunStatus.Success;
                                                   }
                                        )))),
                        new Decorator(
                            ret =>
                            !SpellManager.HasSpell("Stance of the Wise Serpent") &&
                            Me.HealthPercent < THSettings.Instance.SFood &&
                            !Me.IsSwimming && Me.HealthPercent <= THSettings.Instance.SStartEating &&
                            !Me.HasAura("Food") && Consumable.GetBestFood(false) != null && !Me.IsCasting,
                            new PrioritySelector(
                                new Decorator(
                                    new Action(delegate
                                                   {
                                                       Thread.Sleep(TimeSpan.FromMilliseconds(300));

                                                       if (!Me.HasAura("Food"))
                                                       {
                                                           Styx.CommonBot.Rest.FeedImmediate();
                                                           StyxWoW.SleepForLagDuration();
                                                       }

                                                       if (Me.HasAura("Food") &&
                                                           Me.HealthPercent <
                                                           THSettings.Instance.SDoNotHealAbove &&
                                                           !Me.Combat)
                                                       {
                                                           return RunStatus.Running;
                                                       }
                                                       return RunStatus.Success;
                                                   }
                                        ))))
                        ));
        }

        #endregion

        #region SetAutoAttack

        public Composite SetAutoAttack()
        {
            return new Action(delegate
                                  {
                                      if (Me.Combat && Me.IsAutoAttacking && Me.CurrentTarget != null &&
                                          Me.CurrentTarget.IsValid &&
                                          (Me.CurrentTarget.HasAura("Water Shield") && Me.CurrentTarget.IsPlayer &&
                                           Me.IsFFAPvPFlagged ||
                                           DebuffCCBreakonDamage(Me.CurrentTarget) > 0 || Invulnerable(Me.CurrentTarget) ||
                                           !THSettings.Instance.SAutoAttack))
                                      {
                                          //Logging.Write("Stop Attack");
                                          Lua.DoString("RunMacroText('/stopattack');");
                                      }

                                      //Disable this, it conflic with the targeting system
                                      //if (Me.Combat && THSettings.Instance.SAutoAttack && !Me.IsAutoAttacking &&
                                      //    Me.CurrentTarget != null && Me.CurrentTarget.IsValid &&
                                      //    IsEnemy(Me.CurrentTarget) && !Invulnerable(Me.CurrentTarget) &&
                                      //    DebuffCCBreakonDamage(Me.CurrentTarget) <= 0)
                                      //{
                                      //    //Logging.Write("Start Attack");
                                      //    Lua.DoString("RunMacroText('/startattack');");
                                      //}
                                      return RunStatus.Failure;
                                  });
        }

        #endregion

        #region SpellType

        private static readonly HashSet<string> AttackSpells = new HashSet<string>
                                                                   {
                                                                       "Blackout Kick",
                                                                       "Breath of Fire",
                                                                       "Crackling Jade Lightning",
                                                                       "Dizzying Haze",
                                                                       "Energizing Brew",
                                                                       "Flying Serpent Kick",
                                                                       "Invoke Xuen, the White Tiger",
                                                                       "Jab",
                                                                       "Keg Smash",
                                                                       "Leer of the Ox",
                                                                       "Path of Blossoms",
                                                                       "Provoke",
                                                                       "Rising Sun Kick",
                                                                       "Roll",
                                                                       "Spinning Crane Kick",
                                                                       "Spinning Fire Blossom",
                                                                       "Tiger Palm",
                                                                       "Tigereye Brew",
                                                                       "Touch of Death",
                                                                   };

        private static readonly HashSet<string> DefendSpells = new HashSet<string>
                                                                   {
                                                                       "Avert Harm",
                                                                       "Dampen Harm",
                                                                       "Detox",
                                                                       "Diffuse Magic",
                                                                       "Elusive Brew",
                                                                       "Enveloping Mist",
                                                                       "Fortifying Brew",
                                                                       "Guard",
                                                                       "Healing Sphere",
                                                                       "Mana Tea",
                                                                       "Purifying Brew",
                                                                       "Renewing Mist",
                                                                       "Resuscitate",
                                                                       "Soothing Mist",
                                                                       "Summon Black Ox Statue",
                                                                       "Summon Jade Serpent Statue",
                                                                       "Surging Mist",
                                                                       "Transcendence",
                                                                       "Transcendence: Transfer",
                                                                       "Uplift",
                                                                       "Zen Meditation",
                                                                       "Zen Sphere",
                                                                   };

        private static readonly HashSet<string> SpecialSpells = new HashSet<string>
                                                                    {
                                                                        "Charging Ox Wave",
                                                                        "Clash",
                                                                        "Disable",
                                                                        "Fists of Fury",
                                                                        "Grapple Weapon",
                                                                        "Leg Sweep",
                                                                        "Paralysis",
                                                                        "Spear Hand Strike",
                                                                    };

        #endregion

        #region StopCastingCheck

        public void StopCastingCheck()
        {
            if (Me.IsChanneling && Me.ChanneledCastingSpellId == 115175 &&
                GetUnitSoothingMist() && UnitSoothingMist.HealthPercent > THSettings.Instance.SDoNotHealAbove)
            {
                SpellManager.StopCasting();
                Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Soothing Mist, full HP");
            }

            //116694 Surging Mist //Enveloping Mist 124682
            if ((Me.CurrentMap.IsBattleground || Me.CurrentMap.IsArena) &&
                Me.IsCasting &&
                (Me.CurrentCastId == 116694 || Me.CurrentCastId == 124682))
            {
                SpellManager.StopCasting();
                Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Don't Hard Cast in PvP");
            }

            if (Me.IsCasting && Me.ChanneledCastingSpellId == 115294 && Me.ManaPercent > 90)
            {
                SpellManager.StopCasting();
                Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Full Mana");
            }

            //Stop Casting Healing Spells
            //if (Me.IsCasting &&
            //    (Me.CastingSpell.Name == "Soothing Mist" || Me.CastingSpell.Name == "Flash of Light" ||
            //     Me.CastingSpell.Name == "Divine Light"))
            //{
            //    if (LastCastUnit != null && (!LastCastUnit.IsValid || !LastCastUnit.IsAlive))
            //    {
            //        UnitHeal = null;
            //        SpellManager.StopCasting();
            //        Blacklist.Add(LastCastUnit.Guid, TimeSpan.FromSeconds(2));
            //        Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit is Dead");
            //    }
            //    else
            //    {
            //        if (Me.IsCasting && LastCastUnit != null && LastCastUnit.IsValid &&
            //            Me.CastingSpell.Name == "Divine Light" &&
            //            (LastCastUnit.HealthPercent >= THPSettings.Instance.SDoNotHealAbove
            //             ||
            //             LastCastUnit.HealthPercent >= THPSettings.Instance.SDivineLight + 20))
            //        {
            //            SpellManager.StopCasting();
            //            Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Save Mana Divine Light");
            //        }

            //        if (Me.IsCasting && LastCastUnit != null && LastCastUnit.IsValid &&
            //            Me.CastingSpell.Name == "Flash of Light" &&
            //            (LastCastUnit.HealthPercent >= THPSettings.Instance.SDoNotHealAbove
            //             || LastCastUnit.HealthPercent >= THPSettings.Instance.SFlashofLight + 20))
            //        {
            //            SpellManager.StopCasting();
            //            Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Save Mana Flash of Light");
            //        }

            //        if (Me.IsCasting && LastCastUnit != null && LastCastUnit.IsValid &&
            //            Me.CastingSpell.Name == "Holy Light" &&
            //            Me.CurrentCastTimeLeft.TotalMilliseconds > 300 &&
            //            LastCastUnit.HealthPercent < THPSettings.Instance.SDivineLight &&
            //            (LastCastUnit.Combat || Me.Combat))
            //        {
            //            SpellManager.StopCasting();
            //            Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting Holy Light. Need Faster Heal!");
            //        }

            //        if (Me.IsCasting &&
            //            Me.CastingSpell.Name == "Divine Light" && Me.GetAuraById(54149) == null &&
            //            (Me.CurrentMap.IsBattleground || Me.CurrentMap.IsArena))
            //        {
            //            SpellManager.StopCasting();
            //            Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting " + LastCastSpell +
            //                          ": No Infusion of Light");
            //        }

            //        if (Me.IsCasting && LastCastUnit != null && LastCastUnit.IsValid &&
            //            LastCastUnit.HealthPercent > THPSettings.Instance.SDoNotHealAbove)
            //        {
            //            UnitHeal = null;
            //            SpellManager.StopCasting();
            //            Blacklist.Add(LastCastUnit.Guid, TimeSpan.FromSeconds(2));
            //            Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit Full HP");
            //        }

            //        if (Me.IsCasting && LastCastUnit != null && LastCastUnit.IsValid && !LastCastUnit.InLineOfSpellSight)
            //        {
            //            UnitHeal = null;

            //            SpellManager.StopCasting();
            //            Blacklist.Add(LastCastUnit.Guid, TimeSpan.FromSeconds(2));
            //            Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit not In Line of Spell Sight");
            //        }

            //        if (Me.IsCasting && LastCastUnit != null && LastCastUnit.IsValid && LastCastUnit.Distance > 40)
            //        {
            //            UnitHeal = null;
            //            SpellManager.StopCasting();
            //            Blacklist.Add(LastCastUnit.Guid, TimeSpan.FromSeconds(2));
            //            Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit out of range");
            //        }
            //    }
            //}

            //Stop Casting Dps Spells
            //if (Me.IsCasting && Me.CastingSpell.Name == "Denounce")
            //{
            //    if (LastCastUnit != null && (!LastCastUnit.IsValid || !LastCastUnit.IsAlive))
            //    {
            //        UnitAttack = null;
            //        SpellManager.StopCasting();
            //        Blacklist.Add(LastCastUnit.Guid, TimeSpan.FromSeconds(2));
            //        Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit is Dead");
            //    }
            //    else
            //    {
            //        if (Me.IsCasting && LastCastUnit != null && LastCastUnit.IsValid && !LastCastUnit.InLineOfSpellSight)
            //        {
            //            UnitAttack = null;
            //            SpellManager.StopCasting();
            //            Blacklist.Add(LastCastUnit.Guid, TimeSpan.FromSeconds(2));
            //            Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit not In Line of Spell Sight");
            //        }
            //        if (Me.IsCasting && LastCastUnit != null && LastCastUnit.IsValid && LastCastUnit.Distance > 30)
            //        {
            //            UnitAttack = null;
            //            SpellManager.StopCasting();
            //            Blacklist.Add(LastCastUnit.Guid, TimeSpan.FromSeconds(2));
            //            Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit out of range");
            //        }
            //        if (UnitHeal != null && UnitHeal.IsValid &&
            //            UnitHeal.HealthPercent < THPSettings.Instance.SAttackMode)
            //        {
            //            SpellManager.StopCasting();
            //            Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting Denounce: Need Heal First");
            //        }
            //    }
            //}
        }

        #endregion

        #region TalentSort

        public byte TalentSort(WoWUnit target)
        {
            if (target == null)
            {
                return 0;
            }

            if (target.Class == WoWClass.DeathKnight)
            {
                return 1;
            }

            if (target.Class == WoWClass.Druid)
            {
                if (target.Buffs.ContainsKey("Moonkin Form"))
                    return 3;
                if ((target.Buffs.ContainsKey("Leader of the Pack") &&
                     target.Buffs["Leader of the Pack"].CreatorGuid == target.Guid) || target.MaxMana < 40000)
                    return 1;
                return 4;
            }

            if (target.Class == WoWClass.Hunter)
            {
                return 2;
            }

            if (target.Class == WoWClass.Mage)
            {
                return 3;
            }

            if (target.Class == WoWClass.Paladin)
            {
                if (target.MaxMana >= 80000)
                    return 4;
                return 1;
            }

            if (target.Class == WoWClass.Priest)
            {
                if (target.HasAura("Shadowform"))
                    return 3;
                return 4;
            }

            if (target.Class == WoWClass.Rogue)
            {
                return 1;
            }

            if (target.Class == WoWClass.Shaman)
            {
                if (target.MaxMana < 40000)
                    return 1;
                if (target.Buffs.ContainsKey("Elemental Oath") &&
                    target.Buffs["Elemental Oath"].CreatorGuid == target.Guid)
                    return 3;
                return 4;
            }

            if (target.Class == WoWClass.Warlock)
            {
                return 3;
            }

            if (target.Class == WoWClass.Warrior)
            {
                return 1;
            }

            return 0;
        }

        public byte TalentSortSimple(WoWUnit target)
        {
            byte sortSimple = TalentSort(target);

            if (sortSimple == 4)
            {
                return 4;
            }

            if (sortSimple < 4 && sortSimple > 0)
            {
                return 1;
            }

            return 0;
        }

        #endregion

        #region UpdateStatusEvent

        public void UpdateStatusEvent(object sender, LuaEventArgs args)
        {
            THSettings.Instance.UpdateStatus = true;
        }

        #endregion

        #region OnBotStartedEvent

        private void OnBotStartedEvent(object o)
        {
            Logging.Write("----------------------------------");
            Logging.Write("Update Status on Bot Start");
            Logging.Write("----------------------------------");
            THSettings.Instance.UpdateStatus = true;
        }

        #endregion

        #region UpdateCurrentMap

        //public string CurrentMap;

        //private void UpdateCurrentMapEvent(BotEvents.Player.MapChangedEventArgs args)
        //{
        //    THSettings.Instance.UpdateStatus = true;
        //}

        //public void UpdateCurrentMap()
        //{
        //    if (Me.CurrentMap.IsArena)
        //    {
        //        CurrentMap = "Arena";
        //    }
        //    else if (Me.CurrentMap.IsBattleground && Me.IsFFAPvPFlagged)
        //    {
        //        CurrentMap = "Rated Battleground";
        //    }
        //    else if (Me.CurrentMap.IsBattleground)
        //    {
        //        CurrentMap = "Battleground";
        //    }
        //    else if (Me.CurrentMap.IsDungeon)
        //    {
        //        CurrentMap = "Dungeon";
        //    }
        //    else if (Me.CurrentMap.IsRaid)
        //    {
        //        CurrentMap = "Raid";
        //    }
        //    else
        //    {
        //        CurrentMap = "World";
        //    }

        //    Logging.Write("----------------------------------");
        //    Logging.Write("CurrentMap: " + CurrentMap);
        //    Logging.Write("----------------------------------");
        //}

        #endregion

        #region UpdateMyLatency

        public double MyLatency = 0;

        public void UpdateMyLatency()
        {
            if (THSettings.Instance.SLagTolerance)
            {
                //If SLagTolerance enabled, start casting next spell MyLatency Millisecond before GlobalCooldown ready.

                MyLatency = (StyxWoW.WoWClient.Latency);

                //Use here because Lag Tolerance cap at 400
                //Logging.Write("----------------------------------");
                //Logging.Write("MyLatency: " + MyLatency);
                //Logging.Write("----------------------------------");

                if (MyLatency > 400)
                {
                    //Lag Tolerance cap at 400
                    MyLatency = 400;
                }
            }
            else
            {
                MyLatency = 0;
            }
        }

        #endregion

        #region UpdateMyTalent

        public static string HasTalent = "";

        public void UpdateMyTalentEvent(object sender, LuaEventArgs args)
        {
            UpdateMyTalent();
        }

        public void UpdateMyTalent()
        {
            HasTalent = "";
            for (int i = 1; i <= 18; i++)
            {
                HasTalent = HasTalent +
                            Lua.GetReturnVal<String>(
                                string.Format(
                                    "local t= select(5,GetTalentInfo({0})) if t == true then return '['..select(1,GetTalentInfo({0}))..'] ' end return nil",
                                    i), 0);
            }

            Logging.Write("----------------------------------");
            Logging.Write("Talent:");
            Logging.Write(HasTalent);
            Logging.Write("----------------------------------");
        }

        #endregion

        #region UseHealthstone

        public Composite UseHealthstone()
        {
            return
                new Decorator(
                    ret =>
                    Me.Combat && Me.HealthPercent < THSettings.Instance.SHealthStone && Me.CurrentTarget != null &&
                    Me.CurrentTarget.CurrentHealth > Me.HealthPercent,
                    new Action(delegate
                                   {
                                       WoWItem hs = Me.BagItems.FirstOrDefault(o => o.Entry == 5512); //5512 Healthstone
                                       if (hs != null && hs.CooldownTimeLeft.TotalMilliseconds <= MyLatency)
                                       {
                                           hs.Use();
                                           //Lua.DoString("RunMacroText(\"/s Used Healthstone\")");
                                           Logging.Write("Use Healthstone at " + Me.HealthPercent + "%");
                                       }
                                       return RunStatus.Failure;
                                   })
                    );
        }

        #endregion

        #region UpdateMyGlyph

        // [Glyph of Beacon of Light] [Glyph of Harsh Words]
        public static string HasGlyph = "";

        public static string NoGCDSpells =
            "[Fortifying Brew] [Spear Hand Strike] [Invoke Xuen, the White Tiger] [Roll] [Clash] [Provoke] [Leer of the Ox] [Purifying Brew] [Elusive Brew] [Tigereye Brew] [Energizing Brew] [Chi Torpedo] [Energy Brew] [Zen Meditation]";


        public void UpdateMyGlyphEvent(object sender, LuaEventArgs args)
        {
            UpdateMyGlyph();
        }

        public void UpdateMyGlyph()
        {
            HasGlyph = "";
            var glyphCount = Lua.GetReturnVal<int>("return GetNumGlyphSockets()", 0);

            if (glyphCount != 0)
            {
                for (int i = 1; i <= glyphCount; i++)
                {
                    string lua =
                        String.Format(
                            "local enabled, glyphType, glyphTooltipIndex, glyphSpellID, icon = GetGlyphSocketInfo({0});if (enabled) then return glyphSpellID else return 0 end",
                            i);

                    var glyphSpellId = Lua.GetReturnVal<int>(lua, 0);

                    try
                    {
                        if (glyphSpellId > 0)
                        {
                            HasGlyph = HasGlyph + "[" + (WoWSpell.FromId(glyphSpellId)) + "] ";
                        }
                        else
                        {
                            Logging.Write("Glyphdetection - No Glyph in slot " + i);
                            //TreeRoot.Stop();
                        }
                    }
                    catch (Exception ex)
                    {
                        Logging.Write("We couldn't detect your Glyphs");
                        Logging.Write("Report this message to us: " + ex);
                        //TreeRoot.Stop();
                    }
                }
            }

            Logging.Write("----------------------------------");
            Logging.Write("Glyph:");
            Logging.Write(HasGlyph);
            Logging.Write("----------------------------------");
        }

        #endregion

        #region UpdateStatus

        public void UpdateStatus()
        {
            if (THSettings.Instance.UpdateStatus)
                if (Me.IsValid && StyxWoW.IsInGame && StyxWoW.IsInWorld)
                {
                    {
                        Logging.Write("----------------------------------");
                        Logging.Write("Building Rotation base on current Talents and Glyphs......");
                        Logging.Write("----------------------------------");
                        Logging.Write("");

                        //if (TreeRoot.Current.Name != "Questing" && 
                        //    TreeRoot.Current.Name != "Grind Bot" &&
                        //    TreeRoot.Current.Name != "LazyRaider" && 
                        //    TreeRoot.Current.Name != "BGBuddy" &&
                        //    TreeRoot.Current.Name != "DungeonBuddy" && 
                        //    TreeRoot.Current.Name != "Mixed Mode" && 
                        //    GetAsyncKeyState(Keys.F10) == 0)
                        //{
                        //    Logging.Write("This CC only work with DungeonBuddy - LazyRaider - Questing - Grind Bot.");
                        //    Logging.Write("Custom Class Stop.");

                        //    TreeRoot.Stop();
                        //}

                        if (TreeRoot.Current.Name == "LazyRaider" && !THSettings.Instance.SMoveToTarget)
                        {
                            THSettings.Instance.EnableMovement = false;
                            //Logging.Write(LogLevel.Diagnostic,
                            //              "EnableMovement: " + THSettings.Instance.EnableMovement);
                        }
                        else
                        {
                            THSettings.Instance.EnableMovement = true;
                            THSettings.Instance.SAutoTarget = true;
                            //Logging.Write(LogLevel.Diagnostic,
                            //              "EnableMovement: " + THSettings.Instance.EnableMovement);
                        }

                        //if (Me.Level < 85)
                        //{
                        //    Logging.Write("This CC only work on Level 85-90.");
                        //    //TreeRoot.Stop();
                        //    return;
                        //}


                        ReadXML();

                        UpdateMyTalent();

                        UpdateMyGlyph();

                        UpdateMyLatency();

                        GCDReady = DateTime.Now;

                        //i = 1;
                        //foreach (var aura in Me.GetAllAuras())
                        //{
                        //    Logging.Write(i + ". GetAllAuras(): " + aura.Name);
                        //    i = i + 1;
                        //}

                        //i = 1;
                        //foreach (var aura in Me.Auras)
                        //{
                        //    Logging.Write(i + ". Auras: " + aura.Name);
                        //    i = i + 1;
                        //}

                        //Logging.Write("----------------------------------");
                        //int i = 1;
                        //foreach (var aura in Me.ActiveAuras)
                        //{
                        //    Logging.Write(i + ". GetAllAuras(): " + aura.Value.Name + "(" +
                        //                  aura.Value.SpellId + ") - TotalMilliseconds: " +
                        //                  aura.Value.TimeLeft.TotalMilliseconds +
                        //                  " - DispelType: " + aura.Value.Spell.DispelType + " ");
                        //    i = i + 1;
                        //}
                        //Logging.Write("----------------------------------");

                        //var i = 1;
                        //foreach (var spell in SpellManager.Spells)
                        //{
                        //    Logging.Write(i + ". " + spell.Value.Name);
                        //    i = i + 1;
                        //}

                        Logging.Write("----------------------------------");
                        Logging.Write("Building Rotation Completed");
                        Logging.Write("----------------------------------");
                        //Logging.Write(
                        //    "If you change Talent or Glyph, just click Class Config to rebuild rotation, restart Honorbuddy is not required.");
                        //Logging.Write("----------------------------------");
                        Logging.Write("");

                        THSettings.Instance.UpdateStatus = false;
                    }
                }
        }

        #endregion

        #region ValidUnit

        public bool ValidUnit(WoWUnit u)
        {
            if (u == null || !u.IsValid || !u.Attackable || !u.IsAlive || !u.CanSelect ||
                u.IsCritter && (u.CurrentTarget == null || u.CurrentTarget != null && u.CurrentTarget != Me) ||
                u.IsNonCombatPet || Blacklist.Contains(u.Guid))
            {
                return false;
            }
            return true;
        }

        #endregion
    }
}